package com.cet.designapplication.service;

import com.cet.designapplication.mediator.AbstractCustomer;
import com.cet.designapplication.mediator.Buyer;
import com.cet.designapplication.mediator.Mediator;
import com.cet.designapplication.mediator.Payer;
import com.cet.designapplication.ordermanagement.state.OrderState;
import com.cet.designapplication.ordermanagement.state.OrderStateChangeAction;
import com.cet.designapplication.pay.facade.PayFacade;
import com.cet.designapplication.pojo.Order;
import com.cet.designapplication.service.inter.OrderServiceInterface;
import com.cet.designapplication.utils.RedisCommonProcessor;
import org.aspectj.weaver.ast.Or;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.persist.StateMachinePersister;
import org.springframework.stereotype.Service;

import javax.print.DocFlavor;
import java.math.BigDecimal;
import java.util.HashMap;

/**
 * @author NSOC
 */

@Service
public class OrderService implements OrderServiceInterface {

    @Autowired
    private StateMachine<OrderState, OrderStateChangeAction> orderStateMachine;

    @Autowired
    private StateMachinePersister<OrderState, OrderStateChangeAction, String> stateMachineRedisPersister;

    @Autowired
    private RedisCommonProcessor redisCommonProcessor;

    @Autowired
    private PayFacade payFacade;

    @Autowired
    private Mediator mediator;

    @Override
    public Order createOrder(String productId) {
        String orderId = "OID" + productId;
        Order order = Order.builder()
                .orderId(orderId)
                .productId(productId)
                .orderState(OrderState.ORDER_WAIT_PAY)
                .build();
        redisCommonProcessor.set(order.getOrderId(), order, 900);
        return order;
    }

    @Override
    public Order pay(String orderId) {
        // 存在雷点
        Order order = (Order) redisCommonProcessor.get(orderId);
        Message<OrderStateChangeAction> message = MessageBuilder.withPayload(OrderStateChangeAction.PAY_ORDER)
                .setHeader("order", order)
                .build();
        if (changeStateAction(message, order)) {
            return order;
        }
        return null;
    }

    @Override
    public Order send(String orderId) {
        Order order = (Order) redisCommonProcessor.get(orderId);
        Message<OrderStateChangeAction> message = MessageBuilder.withPayload(OrderStateChangeAction.SEND_ORDER)
                .setHeader("order", order)
                .build();
        if (changeStateAction(message, order)) {
            return order;
        }
        return null;
    }

    @Override
    public Order receive(String orderId) {
        Order order = (Order) redisCommonProcessor.get(orderId);
        Message<OrderStateChangeAction> message = MessageBuilder.withPayload(OrderStateChangeAction.RECEIVE_ORDER)
                .setHeader("order", order)
                .build();
        if (changeStateAction(message, order)) {
            redisCommonProcessor.remove(order.getOrderId() + "STATE");
            return order;
        }
        return null;
    }

    @Override
    public String getPayUrl(String orderId, BigDecimal price, Integer payType) {
        Order order = (Order) redisCommonProcessor.get(orderId);
        order.setPrice(price);
        return payFacade.pay(order, payType);
    }

    public void friendPay(String sourceCustomer, String orderId, String targetCustomer, String payResult, String role) {
        Buyer buyer = new Buyer(orderId, mediator, sourceCustomer);
        Payer payer = new Payer(orderId, mediator, sourceCustomer);
        HashMap<String, AbstractCustomer> map = new HashMap<>();
        map.put("buyer", buyer);
        map.put("payer", payer);
        Mediator.customerInstance.put(orderId, map);
        if ("B".equals(role)) {
            buyer.messageTransfer(orderId, targetCustomer, payResult);
        } else if ("P".equals(role)) {
            payer.messageTransfer(orderId, targetCustomer, payResult);
        }
    }

    private boolean changeStateAction(Message<OrderStateChangeAction> message, Order order) {
        try {
            orderStateMachine.start();
            stateMachineRedisPersister.restore(orderStateMachine, order.getOrderId() + "STATE");
            boolean res = orderStateMachine.sendEvent(message);
            stateMachineRedisPersister.persist(orderStateMachine, order.getOrderId() + "STATE");
            return res;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            orderStateMachine.stop();
        }
        return false;
    }
}
